#include "StdAfx.h"
#include ".\neuralnetviz.h"

#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>

#include "glMatrixScope.h"

NeuralNetViz::NeuralNetViz(void)
{
}

NeuralNetViz::~NeuralNetViz(void)
{
}

void NeuralNetViz::Draw()
{
	glMatrixScope lclMatrixScope;

	glDisable(GL_CULL_FACE);

	

	static GLfloat lclLightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	static GLfloat lclLightAmbDiffuse[] = { 0.2f, 0.0f, 0.7f, 1.0f };
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,lclLightSpecular);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, lclLightAmbDiffuse);
	glMateriali(GL_FRONT_AND_BACK, GL_SHININESS,128);

	glColor3d(1.0, 0.0, 0.0);

	glScaled(100.0, 100.0, 100.0);

	int nSteps = 100;
	int nStepsHalf = 50;

	double lfScale = 2.0/nSteps;
	for(int i = 0; i < nSteps; ++i)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for(int j = 0; j < nSteps; ++j)
		{
			mdsVector<3, double> vecSurfPos;
			vecSurfPos[0] = lfScale*(i-nStepsHalf);
			vecSurfPos[1] = lfScale*(j-nStepsHalf);

			GLdouble arrLfNorm[3];

			const double * pLfTmp = m_nnet.Eval(vecSurfPos.GetArr());
			vecSurfPos[2] = *pLfTmp;

			

			const double * pLfPartials = m_nnet.GetPartialDerivatives(vecSurfPos.GetArr(), 0, arrLfNorm);

			arrLfNorm[2] = 1.0;
			arrLfNorm[1] = -pLfPartials[1];
			arrLfNorm[0] = -pLfPartials[0];

			double lfNormScale = 1.0/sqrt(1.0+arrLfNorm[1]*arrLfNorm[1]+arrLfNorm[0]*arrLfNorm[0]);

			arrLfNorm[0] *= 100.0*lfNormScale; arrLfNorm[1] *= 100.0*lfNormScale; arrLfNorm[2] *= 100.0*lfNormScale; 

			glNormal3d(arrLfNorm[0], arrLfNorm[1], arrLfNorm[2]);

			glVertex3dv(static_cast<const GLdouble *>(vecSurfPos.GetArr()));

			vecSurfPos[0] += lfScale;

			pLfTmp = m_nnet.Eval(vecSurfPos.GetArr());

			vecSurfPos[2] = *pLfTmp;

			

			pLfPartials = m_nnet.GetPartialDerivatives(vecSurfPos.GetArr(), 0, arrLfNorm);

			arrLfNorm[2] = 1.0;
			arrLfNorm[1] = -pLfPartials[1];
			arrLfNorm[0] = -pLfPartials[0];

			lfNormScale = 1.0/sqrt(1.0+arrLfNorm[1]*arrLfNorm[1]+arrLfNorm[0]*arrLfNorm[0]);

			arrLfNorm[0] *= 100.0*lfNormScale; arrLfNorm[1] *= 100.0*lfNormScale; arrLfNorm[2] *= 100.0*lfNormScale; 

			glNormal3d(arrLfNorm[0], arrLfNorm[1], arrLfNorm[2]);

			glVertex3dv(static_cast<const GLdouble *>(vecSurfPos.GetArr()));
		}

		glEnd();
	}
}
